package com.sztz.handle;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import com.sztz.result.BaseResult;
import com.sztz.result.ResultEnum;
import com.sztz.result.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.naming.AuthenticationException;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 全局异常统一处理
 * @author yzy
 * @date 2022/7/9 14:11
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 处理 json 请求体调用接口对象参数校验失败抛出的异常
     * @author yzy
     * @date 2022/7/9 14:40
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public BaseResult jsonParamsException(MethodArgumentNotValidException e) {
        log.error(ExceptionUtil.stacktraceToString(e));
        BindingResult bindingResult = e.getBindingResult();
        List<String> errorList = bindingResult.getFieldErrors().stream().map(item -> String.format("%s%s；", item.getField(), item.getDefaultMessage())).collect(Collectors.toList());
        return BaseResult.fail(ResultEnum.PARAMETER_ERROR, errorList);
    }
    /**
     * 处理单个参数校验失败抛出的异常
     * @author yzy
     * @date 2022/7/9 15:23
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public BaseResult paramsException(ConstraintViolationException e) {
        log.error(ExceptionUtil.stacktraceToString(e));
        List<String> errorList = e.getConstraintViolations().stream().map(item -> {
            String[] pathArr = StrUtil.splitToArray(item.getPropertyPath().toString(), StrUtil.C_DOT);
            return StrUtil.concat(Boolean.TRUE,pathArr[1],item.getMessage());
        }).collect(Collectors.toList());
        return BaseResult.fail(ResultEnum.PARAMETER_ERROR, errorList);
    }
    /**
     * 处理 form data方式调用接口对象参数校验失败抛出的异常
     * @author yzy
     * @date 2022/7/9 16:11
     */
    @ExceptionHandler(BindException.class)
    public BaseResult formDaraParamsException(BindException e) {
        log.error(ExceptionUtil.stacktraceToString(e));
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        List<String> collect = fieldErrors.stream()
                .map(o -> o.getField() + o.getDefaultMessage())
                .collect(Collectors.toList());
        return BaseResult.fail(ResultEnum.PARAMETER_ERROR, collect);
    }
    /**
     * 请求方法不被允许异常,GET方式请求POST接口，或POST方式请求GET接口
     * @author yzy
     * @date 2022/7/9 16:11
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public BaseResult httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        log.error(ExceptionUtil.stacktraceToString(e));
        return BaseResult.fail(ResultEnum.METHOD_NOT_SUPPORTED);
    }
    /**
     * 请求类型异常 Content-Type不匹配
     * @author yzy
     * @date 2022/7/9 16:11
     */
    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public BaseResult httpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
        log.error(ExceptionUtil.stacktraceToString(e));
        return BaseResult.fail(ResultEnum.REQUEST_TYPE_NOT_REQUEST);
    }
    /**
     * 接口不存在跑出异常
     * @author yzy
     * @date 2022/7/9 16:11
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public BaseResult noHandlerFoundException(NoHandlerFoundException e) {
        log.error(ExceptionUtil.stacktraceToString(e));
        return BaseResult.fail(ResultEnum.HANDLE_NOT_MATCH, e.getMessage());
    }
    /**
     * 认证异常捕获
     * @author yzy
     * @date 2022/7/9 16:11
     */
    @ExceptionHandler(AuthenticationException.class)
    public BaseResult authenticationException(AuthenticationException e) {
        log.error(ExceptionUtil.stacktraceToString(e));
        return BaseResult.fail(ResultEnum.UNAUTHORIZED,e.getMessage());
    }
    /**
     * 自定义异常捕获
     * @author yzy
     * @date 2022/7/9 16:11
     */
    @ExceptionHandler(ServiceException.class)
    public BaseResult serviceException(ServiceException e) {
        log.error(ExceptionUtil.stacktraceToString(e));
        return BaseResult.fail(e.getCode(),e.getMessage());
    }
    /**
     * 未知异常捕获
     * @author yzy
     * @date 2022/7/9 16:11
     */
    @ExceptionHandler(Exception.class)
    public BaseResult unKnownException(Exception e) {
        log.error(ExceptionUtil.stacktraceToString(e));
        return BaseResult.fail(ResultEnum.UNKNOWN_ERROR, e.getMessage());
    }
    @ExceptionHandler(MultipartException.class)
    public BaseResult multipartException(MultipartException e){
        Throwable rootCause = e.getRootCause();
        log.info(ExceptionUtil.stacktraceToString(rootCause));
        return BaseResult.fail(ResultEnum.UNKNOWN_ERROR,e.getMessage());
    }
}
